﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Sendz.WebUI.Models;
using System.Web.Security;
using Sendz.WebUI.Authorization;
using Sendz.Model;
using Sendz.WebUI.Helpers;
using System.Configuration;
using Sendz.Domain;

namespace Sendz.WebUI.Controllers
{
    // Ref: http://stackoverflow.com/questions/759519/c-centralizing-repeating-viewdata-in-mvc
    [UserInfo] // Reference UserHelpers.cs for attribute override method; allows global user parameter access
    public class InviteController : AjaxFriendlyController
    {
        #region Repository injection //////////////////////////////////

        // Aggregate repositories, injected by container factory in /Infrastructure
        private readonly IUserRepository dbUser;
        private readonly IIdentityRepository dbIdentity;
        private readonly IFormRepository dbForm;
        private readonly IAutoResponderRepository dbAutoResponder;
        public InviteController(IUserRepository dbUser, IIdentityRepository dbIdentity, IFormRepository dbForm, IAutoResponderRepository dbAutoResponder)
        {
            this.dbUser = dbUser;
            this.dbIdentity = dbIdentity;
            this.dbForm = dbForm;
            this.dbAutoResponder = dbAutoResponder;
        }

        #endregion

        #region Action: Send ////////////////////////

        [Authorize]
        [HttpGet]
        public ActionResult Send()
        {
            var user = Membership.GetUser(true) as CustomMembershipUser;
            var thisUser = dbUser.GetUserByKey((Guid)user.ProviderUserKey);
            var availableInvites = new List<InviteViewModel>();
            if (thisUser.InvitesRemaining > 0)
            {
                for (var i = 1; i <= thisUser.InvitesRemaining; i++)
                    availableInvites.Add(new InviteViewModel() { Id = i });
            }
            return View(availableInvites);
        }

        [Authorize]
        [HttpPost]
        public ActionResult Send(IEnumerable<InviteViewModel> invites, string message)
        {
            if (ModelState.IsValid)
            {
                var user = Membership.GetUser(true) as CustomMembershipUser;
                var thisUser = dbUser.GetUserByKey((Guid)user.ProviderUserKey);
                var invitesRemaining = thisUser.InvitesRemaining;
                var totalInvitesSent = 0;
                var emailHelperer = new EmailHelpers();
                foreach (var invite in invites)
                {
                    if (invite.Email != null && invitesRemaining > 0)
                    {
                        if (dbUser.GetUserByEmail(invite.Email) == null)
                        {
                            var newUserKey = Guid.NewGuid();
                            // Todo: move this text into a resource file or something else a marketer can maintain
                            // Note: copies admin temporarily
                            var emailHelper = new EmailHelpers();
                            if (emailHelper.SendInvite(thisUser, newUserKey, invite.Name, invite.Email, message))
                            {
                                dbUser.CreateTempUser(newUserKey, invite.Name, invite.Email, (Guid)user.ProviderUserKey);
                                invitesRemaining -= 1;
                                totalInvitesSent += 1;
                            }
                        }
                    }
                }
                dbUser.UpdateUserInvites(thisUser.UserKey, invitesRemaining);
                var plurality = (totalInvitesSent > 1) ? "s" : string.Empty;
                TempData["Message"] = (totalInvitesSent > 0) ? "Thanks for sharing our system with your friends!" : "Oops! That didn't work!";
                TempData["MessageScreen"] = (totalInvitesSent > 0) ? "You sent " + totalInvitesSent + " invite" + plurality + " and have " + invitesRemaining + " remaining. If you want more, just send us an email and ask!" : "Sorry, no invites were sent, the email address(es) you entered already exist or had issues sending.";
                var availableInvites = new List<InviteViewModel>();
                if (invitesRemaining > 0)
                {
                    for (var i = 1; i <= invitesRemaining; i++)
                        availableInvites.Add(new InviteViewModel() { Id = i, Email = null });
                }
            }
            ViewData["InviteMessage"] = message;
            return View(invites);
        }

        #endregion

        #region Action: Welcome ////////////////////////////

        [HttpGet]
        public ActionResult Welcome(Guid id)
        {
            // Check for original, unique link use
            var thisUser = dbUser.GetUserByKey(id);
            if (thisUser != null)
            {
                if (!string.IsNullOrEmpty(thisUser.Username))
                {
                    TempData["Message"] = "Sorry, it appears the link you tried was already used...";
                    return Redirect("/Form/List");
                }
            }
            else
            {
                TempData["Message"] = "Sorry, it appears the link you tried has expired...";
                return Redirect("/Form/List");
            }
            return View(thisUser);
        }

        [HttpPost]
        // Ref: note the pattern here; this is proof that ViewModels aren't always needed to include alternate data for comparison
        public ActionResult Welcome(User thisUser, string confirmPassword)
        {
            if (thisUser.Password != confirmPassword)
            {
                ModelState.AddModelError("Password", "Your password needs to match the confirmation password");
                return View(thisUser);
            }
            if (ModelState.IsValid)
            {
                thisUser.Username = thisUser.Username.Trim().ToLowerInvariant();
                var tryUsername = dbUser.GetUserByName(thisUser.Username);
                if (tryUsername != null)
                {
                    ModelState.AddModelError("Username", "Oops! That username is already taken, please try again");
                    return View(thisUser);
                }
                var updateUser = dbUser.GetUserByKey(thisUser.UserKey);
                updateUser.Username = thisUser.Username;
                updateUser.Firstname = thisUser.Firstname;
                updateUser.Lastname = thisUser.Lastname;
                updateUser.Zipcode = thisUser.Zipcode;
                // Provide defaults
                updateUser.ResponsesRemaining = Convert.ToInt16(ConfigurationManager.AppSettings.Get("DefaultResponses"));
                updateUser.InvitesRemaining = Convert.ToInt16(ConfigurationManager.AppSettings.Get("DefaultInvites"));
                if (dbUser.SaveUser(updateUser))
                {
                    // Only bother with password update if the user account saves correctly
                    dbUser.ResetUserPassword(thisUser.UserKey, thisUser.Password);
                    // Todo: make this DRY since it touches on the account controller's duties
                    var provider = new CustomMembershipProvider();
                    // Use thisUser.Password since that is what was used for PW reset
                    var loginSuccessful = provider.ValidateUser(thisUser.Username, thisUser.Password);
                    if (loginSuccessful)
                    {
                        SetAuthenticationCookie(updateUser.Username, false);
                        TempData["Message"] = "Welcome to Frontdesk, " + thisUser.Firstname + "!";
                        return Redirect("/Form/List");
                    }
                }
            }
            return View(thisUser);
        }

        public virtual void SetAuthenticationCookie(string username, bool isPersistent)
        {
            FormsAuthentication.SetAuthCookie(username, isPersistent);
        }

        #endregion
    }
}
